package com.snack.shop.service.impl;

import com.snack.shop.common.BusinessException;
import com.snack.shop.config.WxPayConfig;
import com.snack.shop.dto.WxPayNotifyResult;
import com.snack.shop.dto.WxPayResponseDTO;
import com.snack.shop.entity.Order;
import com.snack.shop.service.WxPayService;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.payments.jsapi.model.QueryOrderByOutTradeNoRequest;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.QueryByOutRefundNoRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * 微信支付服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WxPayServiceImpl implements WxPayService {

    private final WxPayConfig wxPayConfig;
    private final JsapiServiceExtension jsapiService;
    private final RefundService refundService;

    @Override
    public WxPayResponseDTO createPrepayOrder(Order order, String openid) {
        try {
            // 构建预支付请求
            PrepayRequest request = new PrepayRequest();
            
            // 设置商户号
            request.setAppid(wxPayConfig.getAppId());
            request.setMchid(wxPayConfig.getMchId());
            
            // 设置商品描述
            String description = getOrderDescription(order);
            request.setDescription(description);
            
            // 设置商户订单号
            request.setOutTradeNo(order.getOrderNo());
            
            // 设置回调通知地址
            request.setNotifyUrl(wxPayConfig.getNotifyUrl());
            
            // 设置订单金额（单位：分）
            Amount amount = new Amount();
            amount.setTotal(order.getActualAmount().multiply(new BigDecimal("100")).intValue());
            amount.setCurrency("CNY");
            request.setAmount(amount);
            
            // 设置支付者信息
            Payer payer = new Payer();
            payer.setOpenid(openid);
            request.setPayer(payer);
            
            log.info("创建预支付订单请求：orderNo={}, amount={}, openid={}", 
                    order.getOrderNo(), amount.getTotal(), openid);
            
            // 调用微信支付API
            PrepayWithRequestPaymentResponse response = jsapiService.prepayWithRequestPayment(request);
            
            log.info("创建预支付订单成功：orderNo={}", order.getOrderNo());
            
            // 构建返回数据（注意：PrepayWithRequestPaymentResponse已包含所有小程序调起支付需要的参数）
            return WxPayResponseDTO.builder()
                    .timeStamp(response.getTimeStamp())
                    .nonceStr(response.getNonceStr())
                    .packageValue(response.getPackageVal())
                    .signType(response.getSignType())
                    .paySign(response.getPaySign())
                    .build();
                    
        } catch (Exception e) {
            log.error("创建预支付订单失败：orderNo={}", order.getOrderNo(), e);
            throw new BusinessException("创建支付订单失败：" + e.getMessage());
        }
    }

    @Override
    public WxPayNotifyResult queryOrderStatus(String orderNo) {
        try {
            log.info("查询订单支付状态：orderNo={}", orderNo);
            
            // 构建查询请求
            QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
            request.setMchid(wxPayConfig.getMchId());
            request.setOutTradeNo(orderNo);
            
            // 调用查询接口
            Transaction transaction = jsapiService.queryOrderByOutTradeNo(request);
            
            log.info("查询订单支付状态成功：orderNo={}, tradeState={}, transactionId={}", 
                    orderNo, transaction.getTradeState(), transaction.getTransactionId());
            
            // 转换为统一格式
            return convertToNotifyResult(transaction);
            
        } catch (Exception e) {
            log.error("查询订单支付状态失败：orderNo={}", orderNo, e);
            throw new BusinessException("查询支付状态失败：" + e.getMessage());
        }
    }

    @Override
    public WxPayNotifyResult handlePayNotify(String requestBody, String signature, 
                                             String serial, String timestamp, String nonce) {
        try {
            log.info("处理支付回调通知：timestamp={}, nonce={}", timestamp, nonce);
            
            // 创建通知解析器（使用公钥配置）
            NotificationParser parser = new NotificationParser(
                (com.wechat.pay.java.core.RSAPublicKeyConfig) wxPayConfig.config()
            );
            
            // 构建请求参数
            RequestParam requestParam = new RequestParam.Builder()
                    .serialNumber(serial)
                    .nonce(nonce)
                    .signature(signature)
                    .timestamp(timestamp)
                    .body(requestBody)
                    .build();
            
            // 解析并验证签名
            Transaction transaction = parser.parse(requestParam, Transaction.class);
            
            log.info("支付回调通知验证成功：orderNo={}, transactionId={}, tradeState={}", 
                    transaction.getOutTradeNo(), transaction.getTransactionId(), transaction.getTradeState());
            
            // 转换为统一格式
            return convertToNotifyResult(transaction);
            
        } catch (Exception e) {
            log.error("处理支付回调通知失败", e);
            throw new BusinessException("处理支付回调失败：" + e.getMessage());
        }
    }

    @Override
    public String refund(Order order, String refundReason) {
        // 调用重载方法，全额退款
        return refund(order, refundReason, null);
    }

    @Override
    public String refund(Order order, String refundReason, BigDecimal refundAmount) {
        try {
            // 生成退款单号
            String refundNo = "RF" + order.getOrderNo();
            
            // 确定退款金额：如果未指定则全额退款
            BigDecimal actualRefundAmount = refundAmount != null ? refundAmount : order.getActualAmount();
            
            log.info("申请退款：orderNo={}, refundNo={}, totalAmount={}, refundAmount={}, reason={}", 
                    order.getOrderNo(), refundNo, order.getActualAmount(), actualRefundAmount, refundReason);
            
            // 构建退款请求
            CreateRequest request = new CreateRequest();
            request.setOutTradeNo(order.getOrderNo());
            request.setOutRefundNo(refundNo);
            request.setReason(refundReason);
            request.setNotifyUrl(wxPayConfig.getRefundNotifyUrl());
            
            // 设置退款金额（单位：分）
            AmountReq amountReq = new AmountReq();
            int refundAmountFen = actualRefundAmount.multiply(new BigDecimal("100")).intValue();
            int totalAmountFen = order.getActualAmount().multiply(new BigDecimal("100")).intValue();
            
            amountReq.setRefund(Long.valueOf(refundAmountFen)); // 退款金额
            amountReq.setTotal(Long.valueOf(totalAmountFen));   // 原订单金额
            amountReq.setCurrency("CNY");
            request.setAmount(amountReq);
            
            // 调用退款接口
            Refund refund = refundService.create(request);
            
            log.info("申请退款成功：refundNo={}, refundId={}, status={}", 
                    refundNo, refund.getRefundId(), refund.getStatus());
            
            return refundNo;
            
        } catch (Exception e) {
            log.error("申请退款失败：orderNo={}", order.getOrderNo(), e);
            
            // 提取友好的错误信息
            String errorMessage = extractFriendlyErrorMessage(e);
            throw new BusinessException(errorMessage);
        }
    }

    @Override
    public String queryRefundStatus(String refundNo) {
        try {
            log.info("查询退款状态：refundNo={}", refundNo);
            
            // 构建查询请求
            QueryByOutRefundNoRequest request = new QueryByOutRefundNoRequest();
            request.setOutRefundNo(refundNo);
            
            // 调用查询接口
            Refund refund = refundService.queryByOutRefundNo(request);
            
            log.info("查询退款状态成功：refundNo={}, status={}", refundNo, refund.getStatus());
            
            return refund.getStatus().name();
            
        } catch (Exception e) {
            log.error("查询退款状态失败：refundNo={}", refundNo, e);
            throw new BusinessException("查询退款状态失败：" + e.getMessage());
        }
    }

    /**
     * 获取订单描述
     */
    private String getOrderDescription(Order order) {
        switch (order.getOrderType()) {
            case 1:
                return "零食购买订单";
            case 2:
                return "取快递服务";
            case 3:
                return "取外卖服务";
            case 4:
                return "代取奶咖服务";
            default:
                return "订单支付";
        }
    }

    /**
     * 转换Transaction为WxPayNotifyResult
     */
    private WxPayNotifyResult convertToNotifyResult(Transaction transaction) {
        WxPayNotifyResult result = new WxPayNotifyResult();
        result.setMchid(transaction.getMchid());
        result.setAppid(transaction.getAppid());
        result.setOutTradeNo(transaction.getOutTradeNo());
        result.setTransactionId(transaction.getTransactionId());
        result.setTradeType(transaction.getTradeType().name());
        result.setTradeState(transaction.getTradeState().name());
        result.setTradeStateDesc(transaction.getTradeStateDesc());
        result.setBankType(transaction.getBankType());
        result.setAttach(transaction.getAttach());
        result.setSuccessTime(transaction.getSuccessTime());
        
        // 转换支付者信息
        if (transaction.getPayer() != null) {
            WxPayNotifyResult.Payer payer = new WxPayNotifyResult.Payer();
            payer.setOpenid(transaction.getPayer().getOpenid());
            result.setPayer(payer);
        }
        
        // 转换金额信息
        if (transaction.getAmount() != null) {
            WxPayNotifyResult.Amount amount = new WxPayNotifyResult.Amount();
            amount.setTotal(transaction.getAmount().getTotal());
            amount.setPayerTotal(transaction.getAmount().getPayerTotal());
            amount.setCurrency(transaction.getAmount().getCurrency());
            amount.setPayerCurrency(transaction.getAmount().getPayerCurrency());
            result.setAmount(amount);
        }
        
        return result;
    }
    
    /**
     * 提取友好的错误信息
     * 基于微信支付官方文档：https://pay.weixin.qq.com/doc/v3/merchant/4012791903
     */
    private String extractFriendlyErrorMessage(Exception e) {
        String message = e.getMessage();
        
        if (message == null) {
            return "退款处理失败，请稍后重试";
        }
        
        // 【官方业务错误码】基于微信支付API v3文档
        
        // 403 NOT_ENOUGH - 余额不足
        if (message.contains("NOT_ENOUGH") || message.contains("基本账户余额不足")) {
            return "商户账户余额不足，请充值后重试";
        }
        
        // 400 INVALID_REQUEST - 请求参数不符合业务规则
        if (message.contains("INVALID_REQUEST")) {
            return "退款请求参数有误，请检查订单信息";
        }
        
        // 404 RESOURCE_NOT_EXISTS - 订单号不存在
        if (message.contains("RESOURCE_NOT_EXISTS") || message.contains("订单号不存在")) {
            return "订单不存在或未支付，无法退款";
        }
        
        // 429 FREQUENCY_LIMITED - 频率限制
        if (message.contains("FREQUENCY_LIMITED")) {
            return "退款频率过高，请稍后重试";
        }
        
        // 403 USER_ACCOUNT_ABNORMAL - 退款请求失败
        if (message.contains("USER_ACCOUNT_ABNORMAL")) {
            return "用户账户异常，退款失败";
        }
        
        // 404 MCH_NOT_EXISTS - 商户号不存在
        if (message.contains("MCH_NOT_EXISTS")) {
            return "商户号配置错误，请联系技术支持";
        }
        
        // 500 SYSTEM_ERROR - 系统超时
        if (message.contains("SYSTEM_ERROR")) {
            return "微信支付系统繁忙，请稍后重试";
        }
        
        // 400 PARAM_ERROR - 参数错误
        if (message.contains("PARAM_ERROR")) {
            return "请求参数错误，请联系技术支持";
        }
        
        // 401 SIGN_ERROR - 签名错误
        if (message.contains("SIGN_ERROR")) {
            return "签名验证失败，请联系技术支持";
        }
        
        // 尝试从JSON响应中提取message字段
        try {
            if (message.contains("\"message\":\"")) {
                int start = message.indexOf("\"message\":\"") + 11;
                int end = message.indexOf("\"", start);
                if (end > start) {
                    String extractedMsg = message.substring(start, end);
                    if (!extractedMsg.isEmpty()) {
                        return "退款失败：" + extractedMsg;
                    }
                }
            }
        } catch (Exception ex) {
            // 忽略解析异常
        }
        
        // HTTP状态码错误
        if (message.contains("Wrong HttpStatusCode[403]")) {
            return "商户权限不足或账户异常";
        }
        if (message.contains("Wrong HttpStatusCode[404]")) {
            return "订单或商户信息不存在";
        }
        if (message.contains("Wrong HttpStatusCode[429]")) {
            return "请求频率过高，请稍后重试";
        }
        if (message.contains("Wrong HttpStatusCode")) {
            return "微信支付接口调用失败，请稍后重试";
        }
        
        // 默认返回简化的错误信息
        return "退款处理失败，请联系技术支持";
    }
}

